/************************************************************
	File:		Turret.cpp
	Author:		Doug Monroe (dmonroe@fullsail.com)
	Course:		SGD 1304
	Purpose:	CTurret class handles computer-controlled
				turret entities
************************************************************/


#include "Turret.h"

#include "../../SGD Wrappers/CSGD_TextureManager.h"
#include "../../SGD Wrappers/CSGD_EventSystem.h"
#include "../../SGD Wrappers/CSGD_MessageSystem.h"
#include "../../SGD Wrappers/SGD_Math.h"

#include "CreateLaserMessage.h"
#include "DestroyEntityMessage.h"

#include <cassert>


//***********************************************************
// CONSTRUCTOR
CTurret::CTurret(void)
{
	// Set the entity type
	CEntity::m_eType = ENT_TURRET;

	// No target yet
	m_pTargetEntity = nullptr;

	// Register to listen for the "FIRE_LASER" event
	CSGD_EventSystem::GetInstance()->RegisterClient( "FIRE_LASER", this );
}

//***********************************************************
// DESTRUCTOR
CTurret::~CTurret(void)
{
	// Release the target (if any)
	SetTargetEntity( nullptr );


	// Unregister from ALL events
	CSGD_EventSystem::GetInstance()->UnregisterClientAll( this );
}


//***********************************************************
// Update
//	- rotate toward the target
/*virtual*/ void CTurret::Update( float fElapsedTime )
{
	// Move the entity
	CEntity::Update( fElapsedTime );


	// Is there no target?
	if( m_pTargetEntity == nullptr )
		return;


	// Create a vector for the turret's orientation
	tVector2D vOrientation = { 0, -1 };

	// Rotate the vector
	vOrientation = Vector2DRotate( vOrientation, GetRotation() );


	// Create a vector FROM the turret TO the target
	tVector2D vToTarget = 
	{
		m_pTargetEntity->GetPosX() - this->GetPosX(),
		m_pTargetEntity->GetPosY() - this->GetPosY()
	};


	// Calculate the angle between the vectors
	//	ALWAYS BETWEEN 0 -> pi
	float fAngle = AngleBetweenVectors( vOrientation, vToTarget );

	// Rotate slowly at pi/4 per second
	float fMaxAngle = D3DX_PI/4 * fElapsedTime;
	if( fAngle > fMaxAngle )
		fAngle = fMaxAngle;


	// Which way to turn?
	if( Steering( vOrientation, vToTarget ) < 0 )
		fAngle = -fAngle;

	// Increase our rotation
	SetRotation( GetRotation() + fAngle );
}

//***********************************************************
// Render
//	- render the cannon rotated, ontop the base
/*virtual*/ void CTurret::Render( void )
{
	// Validate the image
	assert( GetImageID() != -1 && "CTurret::Render - image was not set" );


	// Draw the base
	RECT rBase = { 0, 0, 32, 32 };
	CSGD_TextureManager::GetInstance()->Draw(
		GetImageID(), (int)GetPosX(), (int)GetPosY(),
		1.0f, 1.0f, &rBase );

	// Draw the cannon rotated
	RECT rCannon = { 32, 0, 64, 32 };
	CSGD_TextureManager::GetInstance()->Draw(
		GetImageID(), (int)GetPosX(), (int)GetPosY() - 11,
		1.0f, 1.0f, &rCannon,
		16.0f, 27.0f, GetRotation() );
}


//***********************************************************
// SetTargetEntity
//	- store a reference to the parameter
void CTurret::SetTargetEntity( CEntity* ptr )
{
	// Release the existing target (if it exists)
	if( m_pTargetEntity != nullptr )
		m_pTargetEntity->Release();

	// Store the parameter
	m_pTargetEntity = ptr;

	// Add a reference to the new target (if it exists)
	if( m_pTargetEntity != nullptr )
		m_pTargetEntity->AddRef();
}


//***********************************************************
// CheckCollision
//	- CShip		- nothing
//	- CTarget	- nothing
//	- CLaser	- self-destruct
/*virtual*/ bool CTurret::CheckCollision( IEntity* pOther )
{
	// What type?
	if( pOther->GetType() == ENT_LASER )
	{
		// Did we collide?
		if( CEntity::CheckCollision( pOther ) == true )
		{
			// Self-destruct
			CDestroyEntityMessage* pMsg = new CDestroyEntityMessage( this );
			CSGD_MessageSystem::GetInstance()->SendMsg( pMsg );
			pMsg = nullptr;


			// The ship earns 5 points
			int nPoints = 5;

			// Send the event IMMEDIATELY to use the local variable
			CSGD_EventSystem::GetInstance()->SendEventNow(
				"INCREASE_SCORE", &nPoints, nullptr, this );


			return true;
		}
	}

	return false;
}



//***********************************************************
// HandleEvent
//	- triggered when an event that we have registered for
//	  is sent to the Event System
/*virtual*/ void CTurret::HandleEvent( CEvent* pEvent )
{
	// What type of event?
	if( pEvent->GetEventID() == "FIRE_LASER" )
	{
		// Is this event for us?
		if( pEvent->GetDestination() == this 
			|| pEvent->GetDestination() == nullptr )	// everybody!
		{

			// Send a CCreateLaserMessage to the Message System
			CCreateLaserMessage* pMsg = new CCreateLaserMessage(
				GetPosX() + GetWidth()/2,
				GetPosY() + GetHeight()/2,
				GetRotation() );

			CSGD_MessageSystem::GetInstance()->SendMsg( pMsg );
			pMsg = nullptr;
		}
	}
}
